package ZuidaZY

import (
	"MerelybG/Common"
	"MerelybG/Common/OSUtils"
	"MerelybG/Download"
	"database/sql"
	"fmt"
	"github.com/PuerkitoBio/goquery"
	_ "github.com/go-sql-driver/mysql"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"
	"sync"
	"time"
)

type DbWorker struct {
	Dsn string
	Db  *sql.DB
}

//视频信息
type ZDZYVideoInfo struct {
	id             int64  "db:id"
	videoName      string "db:video_name"
	videoAlias     string "db:video_alias"
	videoDirector  string "db:video_director"
	videoPerformer string "db:video_performer"
	videoDrama     string "db:video_drama"
	videoType      string "db:video_type"
	videoRegion    string "db:video_region"
	videoLan       string "db:video_lan"
	videoTime      string "db:video_time"
	videoDescribe  string "db:video_describe"
	remark         string "db:remark"
	createTime     int64  "db:create_time"
	createBy       string "db:create_by"
	updateTime     int64  "db:update_time"
	updateBy       string "db:update_by"
	isDelete       int    "db:is_delete"
}

//视频详细下载地址
type ZDZYVideoDetail struct {
	id         int64  "db:id"
	videoId    int64  "db:video_id"
	detailName string "db:detail_name"
	detailUrl  string "db:detail_url"
	remark     string "db:remark"
	createTime int64  "db:create_time"
	createBy   string "db:create_by"
	updateTime int64  "db:update_time"
	updateBy   string "db:update_by"
	isDelete   int    "db:is_delete"
}

//插入视频内容
func insertVideo(dbw *DbWorker, videoInfo ZDZYVideoInfo) int {
	//查询是否有数据
	rows, err := dbw.Db.Query("select * from videoInfo where  id = " + strconv.FormatInt(videoInfo.id, 10) + ";")
	defer rows.Close()
	if !Common.CheckErr("insertVideo", err) {
		//查询错误
		return 2
	}
	if rows.Next() {
		//数据已存在
		return 1
	}

	var strSQL string
	strSQL = "INSERT INTO videoInfo(id, video_name, video_alias, video_director, video_performer, video_drama, " +
		"video_type, video_region, video_lan, video_time, video_describe, remark, create_time, create_by, update_time, " +
		"update_by, is_delete) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,	?);"

	stmt, _ := dbw.Db.Prepare(strSQL)
	defer stmt.Close()

	ret, err := stmt.Exec(videoInfo.id, videoInfo.videoName,
		videoInfo.videoAlias, videoInfo.videoDirector, videoInfo.videoPerformer, videoInfo.videoDrama, videoInfo.videoType,
		videoInfo.videoRegion, videoInfo.videoLan, videoInfo.videoTime, videoInfo.videoDescribe, videoInfo.remark, videoInfo.createTime,
		videoInfo.createBy, videoInfo.updateTime, videoInfo.updateBy, videoInfo.isDelete)

	if !Common.CheckErr("insertVideo", err) {
		return 3
	}
	if LastInsertId, err := ret.LastInsertId(); nil == err {
		fmt.Println("LastInsertId:", LastInsertId)
	}
	return 0
}

//插入视频详情
func insertVideoDetail(dbw *DbWorker, videoDetail ZDZYVideoDetail) (iResult int) {
	//查询是否有数据
	rows, err := dbw.Db.Query("select * from videoDetail where  video_id = " + strconv.FormatInt(videoDetail.videoId, 10) + " and detail_url = '" + strings.Replace(videoDetail.detailUrl, "'", "\\'", -1) + "';")
	defer rows.Close()
	if !Common.CheckErr("insertVideoDetail", err) {
		//查询错误
		return 2
	}
	if rows.Next() {
		return 1
	}

	var strSQL string
	strSQL = "INSERT INTO videoDetail(id, video_id, detail_name, detail_url, remark, create_time, " +
		"create_by, update_time, update_by, is_delete)	VALUES(?, ?, ?,  ?, ?, ?, ?, ?, ?, ?);"

	stmt, _ := dbw.Db.Prepare(strSQL)
	defer stmt.Close()

	ret, err := stmt.Exec(videoDetail.id, videoDetail.videoId, videoDetail.detailName, videoDetail.detailUrl, videoDetail.remark,
		videoDetail.createTime, videoDetail.createBy, videoDetail.updateTime, videoDetail.updateBy, videoDetail.isDelete)

	if !Common.CheckErr("insertVideoDetail", err) {
		return 3
	}
	if LastInsertId, err := ret.LastInsertId(); nil == err {
		fmt.Println("LastInsertId:", LastInsertId)
	}
	return 0
}

/**
详情页
*/
func getVideoDetail(dbw *DbWorker, strUrl string, iDetailId int64) int {
	res, err := http.Get(strUrl)
	Common.CheckErr("getVideoDetail", err)
	defer res.Body.Close()
	if res.StatusCode != 200 {
		log.Fatalf("status code error: %d %s", res.StatusCode, res.Status)
	}
	// Load the HTML document
	docFrame, errFrame := goquery.NewDocumentFromReader(res.Body)
	if !Common.CheckErr("getVideoDetail", errFrame) {
		return 1
	}
	//查找所有div
	docFrame.Find("div").Each(func(iIndex int, selIndex *goquery.Selection) {
		var strAtrr, strId string
		var bAtrr, bId bool
		strAtrr, bAtrr = selIndex.Attr("class")
		if !bAtrr {
			strAtrr = ""
		}

		strId, bId = selIndex.Attr("id")
		if !bId {
			strId = ""
		}

		//详细属性
		if strings.Contains(strAtrr, "vodInfo") {
			var zdzyInfo *ZDZYVideoInfo = new(ZDZYVideoInfo)
			selIndex.Find("div").Each(func(iInfo int, selInfo *goquery.Selection) {
				var strInfo string
				var bInfo bool
				strInfo, bInfo = selInfo.Attr("class")
				if !bInfo {
					strInfo = ""
				}
				//fmt.Println(selInfo.Html())
				//名称
				if strings.Contains(strInfo, "vodh") {
					zdzyInfo.videoName = selInfo.Find("h2").Text()
				}
				//详细
				if strings.Contains(strInfo, "vodinfobox") {
					selInfo.Find("li").Each(func(iVideoInfo int, selVideoInfo *goquery.Selection) {
						switch iVideoInfo {
						case 0:
							//别名
							zdzyInfo.videoAlias = selVideoInfo.Find("span").Text()
						case 1:
							//导演
							zdzyInfo.videoDirector = selVideoInfo.Find("span").Text()
						case 2:
							//演员
							zdzyInfo.videoPerformer = selVideoInfo.Find("span").Text()
						case 3:
							//类型
							if selVideoInfo.Find("span").Children().Length() > 0 {
								zdzyInfo.videoDrama = selVideoInfo.Find("span").Text()
								zdzyInfo.videoType = selVideoInfo.Find("span").Children().Text()
								zdzyInfo.videoDrama = strings.Replace(zdzyInfo.videoDrama, zdzyInfo.videoType, "", -1)
							} else {
								zdzyInfo.videoDrama = ""
								zdzyInfo.videoType = selVideoInfo.Find("span").Text()
							}
						case 4:
							//地区
							zdzyInfo.videoRegion = selVideoInfo.Find("span").Text()
						case 5:
							//语言
							zdzyInfo.videoLan = selVideoInfo.Find("span").Text()
						case 6:
							//上映时间
							zdzyInfo.videoTime = selVideoInfo.Find("span").Text()
						}
					})
				}
			})
			zdzyInfo.id = iDetailId
			zdzyInfo.createTime = time.Now().UnixNano()
			zdzyInfo.createBy = "1"
			zdzyInfo.updateTime = time.Now().UnixNano()
			zdzyInfo.updateBy = "1"
			zdzyInfo.isDelete = 0
			insertVideo(dbw, *zdzyInfo)
		}

		if strings.Contains(strId, "down_1") {
			selIndex.Find("li").Each(func(iDetail int, selDetail *goquery.Selection) {
				var zdzyDetail *ZDZYVideoDetail = new(ZDZYVideoDetail)
				zdzyDetail.id = time.Now().UnixNano()
				zdzyDetail.videoId = iDetailId
				zdzyDetail.detailName = strings.Split(selDetail.Text(), "$")[0]
				zdzyDetail.detailUrl = strings.Split(selDetail.Text(), "$")[1]
				zdzyDetail.createTime = time.Now().UnixNano()
				zdzyDetail.isDelete = 0
				insertVideoDetail(dbw, *zdzyDetail)
			})
		}
	})
	return 0
}

/**
列表页
*/
func getVideoPageUrl(strUrl string) int {
	res, err := http.Get(strUrl)
	Common.CheckErr("getVideoPageUrl", err)
	defer res.Body.Close()
	if res.StatusCode != 200 {
		log.Fatalf("status code error: %d %s", res.StatusCode, res.Status)
	}
	// Load the HTML document
	docFrame, errFrame := goquery.NewDocumentFromReader(res.Body)
	if !Common.CheckErr("getVideoPageUrl", errFrame) {
		return 1
	}
	docFrame.Find("div").Each(func(iIndex int, selPage *goquery.Selection) {
		var strPage string
		var bPage bool
		//获取属性节点
		strPage, bPage = selPage.Attr("class")
		if !bPage {
			strPage = ""
		}
		var dbErr error
		dbw := DbWorker{
			Dsn: "liming:Liming-5258@tcp(47.111.105.225:3306)/video?charset=utf8mb4",
		}
		dbw.Db, dbErr = sql.Open("mysql", dbw.Dsn)
		if dbErr != nil {
			panic(dbErr)
			return
		}
		defer dbw.Db.Close()

		//列表结构位置
		if strings.Contains(strPage, "xing_vb") {
			selPage.Find("span").Each(func(iVideoNum int, selVideo *goquery.Selection) {
				if iVideoNum != 0 {
					selVideo.Find("a").Each(func(iVideoUrl int, selVideoUrl *goquery.Selection) {
						var strPageUrl string
						var bUrl bool
						strPageUrl, bUrl = selVideoUrl.Attr("href")
						if !bUrl {
							strPageUrl = ""
						}
						//fmt.Println(strPageUrl)
						var strId string = strings.Replace(strPageUrl, "/?m=vod-detail-id-", "", -1)
						strId = strings.Replace(strId, ".html", "", -1)
						var iDetailId int64
						iDetailId, err = strconv.ParseInt(strId, 10, 64)
						Common.CheckErr("getVideoPageUrl", err)
						getVideoDetail(&dbw, "http://zuidazy1.net"+strPageUrl, iDetailId)
					})
				}
			})
		}
	})
	return 0
}

func GetVideoInfo() {
	//http://zuidazy1.net/?m=vod-index-pg-3.html
	var strUrl string
	for iPageNum := 0; iPageNum < 781; iPageNum++ {
		if iPageNum == 0 {
			strUrl = "http://zuidazy1.net/?m=vod-index.html"
		} else {
			strUrl = "http://zuidazy1.net/?m=vod-index-pg-" + strconv.Itoa(iPageNum) + ".html"
		}
		getVideoPageUrl(strUrl)
	}
}

func downSchedule(iIdindex int64, schedule float64) {
	fmt.Println(schedule)
}

func downFile(strUrl, strSavePath string, bMuilt bool, iIdIndex int64, threadGroup *sync.WaitGroup,
	scheduleCallback func(iIdIndex int64, schedule float64)) {
	defer threadGroup.Done()
	Download.HttpDownload(strUrl, strSavePath, true, iIdIndex, downSchedule)

}

/**
下载视频
*/
func DownloadVideo(strPath string) int {
	var dbErr error
	dbw := DbWorker{
		Dsn: "liming:Liming-5258@tcp(47.111.105.225:3306)/video?charset=utf8mb4",
	}
	dbw.Db, dbErr = sql.Open("mysql", dbw.Dsn)
	defer dbw.Db.Close()
	if !Common.CheckErr("DownloadVideo", dbErr) {
		return 9
	}

	rows, err := dbw.Db.Query("select count(id) as num FROM videoDetail")
	//rows, err := dbw.Db.Query("SELECT count(id) FROM video.videoDetail where video_id in (select id from video.videoInfo where video_name like '%破产姐妹%')")
	defer rows.Close()
	if !Common.CheckErr("DownloadVideo", err) {
		return 8
	}

	var iDataNum int64
	for rows.Next() {
		var errData error
		errData = rows.Scan(&iDataNum)
		if !Common.CheckErr("DownloadVideo", errData) {
			return 7
		}
	}

	var iTotal int64 = iDataNum / 100
	if iDataNum%100 > 0 {
		iTotal += 1
	}

	var iIndex int64
	for iIndex = 3; iIndex < iTotal; iIndex++ {
		var (
			rowData *sql.Rows
			errQuer error
		)
		rowData, errQuer = dbw.Db.Query("select *  FROM video.videoDetail order by create_time desc limit " + strconv.FormatInt(iIndex*100, 10) + ", 100;")
		//rowData, errQuer = dbw.Db.Query("SELECT * FROM video.videoDetail where video_id in (select id from video.videoInfo where video_name like '%破产姐妹%') " +
		//	"limit " + strconv.FormatInt(iIndex*100, 10) + ", 100;")
		defer rowData.Close()
		if !Common.CheckErr("DownloadVideo", errQuer) {
			return 8
		}
		//var threadGroup = sync.WaitGroup{}
		for rowData.Next() {
			zdzyVideoDetail := ZDZYVideoDetail{}
			var errData error
			errData = rowData.Scan(&zdzyVideoDetail.id, &zdzyVideoDetail.videoId, &zdzyVideoDetail.detailName, &zdzyVideoDetail.detailUrl,
				&zdzyVideoDetail.remark, &zdzyVideoDetail.createTime, &zdzyVideoDetail.createBy, &zdzyVideoDetail.updateTime,
				&zdzyVideoDetail.updateBy, &zdzyVideoDetail.isDelete)
			if !Common.CheckErr("DownloadVideo", errData) {
				return 7
			}

			var strDir string = strconv.FormatInt(zdzyVideoDetail.videoId, 10)
			//文件名称
			var strName string = "\\" + zdzyVideoDetail.detailUrl[strings.LastIndex(zdzyVideoDetail.detailUrl, "/")+1:len(zdzyVideoDetail.detailUrl)]

			if strings.LastIndex(strPath, "\\") == len(strPath)-1 {
				strDir = strPath + strDir
			} else {
				strDir = strPath + "\\" + strDir
			}

			if OSUtils.DirCreateAll(strDir) == 1 {
				return 6
			}
			strName = strDir + strName
			var iReturn int = Download.HttpDownload(zdzyVideoDetail.detailUrl, strName, true, zdzyVideoDetail.id, downSchedule)
			if iReturn != 0 && iReturn != 2 {
				err := os.Remove(strName)
				if err != nil {
					// 删除失败

				} else {
					// 删除成功

				}
			}
			fmt.Println(strName)
			//threadGroup.Add(1)
			//go downFile(zdzyVideoDetail.detailUrl, strName, true, zdzyVideoDetail.id, &threadGroup, downSchedule)
		}
		//threadGroup.Wait()
	}
	return 0
}
